/**
 * 201030：multiText新增align参数（left居左，center居中，right居右）
 * 201106：multiText移除w参数，新增alignV参数（未测试）
 * 201127：增加圆圈加号，更改参数为参数对象
 * 201201：新增长圆形状
 * 201215：增加圆角矩形
 * 210222: 增加渐变，替代常用的场景背景图片
 * 220104：行高比例计入文本字体大小
 * 20220304:[require] to [import]...jordia
 * 20220321:修正THREE.Texture导入修改引起的同名错误
 */

import {Texture as THREETex,LinearFilter} from 'three';

const PI=Math.PI;
const TPI=Math.PI*2;
const HPI=Math.PI*0.5;
const D2R=Math.PI/180;
const RETURN_VALUE=(canvas,paras)=>{
    if(paras['returnCanvas'])return canvas;
    if(paras['returnImage'])return canvas.toDataURL('image/png');
    let tex = new THREETex(canvas);
    tex.minFilter = paras['minFilter']||LinearFilter;
    tex.magFilter = paras['magFilter']||LinearFilter;
    tex.needsUpdate = true;
    return tex;
};

let Texture={};

/**
 * 绘图
 * @param sizeX 宽
 * @param sizeY 高
 * @param img 图源
 * @param values 参数对象
 * @param targetCanvas 绘制到的canvas
 * @returns {RETURN_VALUE.props|*|Texture} values.returnCanvas，返回canvas；values.returnImage,返回url；values.returnTexture，返回贴图（下同）
 */
Texture.image=(sizeX,sizeY,img,values={},targetCanvas=null)=>{
    let canvas=targetCanvas||document.createElement('canvas');
    if(!targetCanvas) {
        canvas.width = sizeX;
        canvas.height = sizeY;
    }
    let ctx=canvas.getContext('2d');
    if(img)ctx.drawImage(img,values.dx||0,values.dy||0,values.width||canvas.width,values.height||canvas.height);
    return RETURN_VALUE(canvas,values);
};

/**
 * 根号
 * @param _width 宽
 * @param _height 高
 * @param drawRatio 缩放
 * @param values 参数对象
 * @param targetCanvas 绘制到的canvas
 * @returns {RETURN_VALUE.props|*|Texture}
 */
Texture.root=(_width=256, _height=128,drawRatio=0.9, values={},targetCanvas=null)=>{
    let width=targetCanvas?targetCanvas.width:_width;
    let height=targetCanvas?targetCanvas.height:_height;
    let canvas=targetCanvas||document.createElement('canvas');
    if(!targetCanvas) {
        canvas.width = width;
        canvas.height = height;
    }
    let ctx=canvas.getContext('2d');
    let hi=height*drawRatio;
    let wi=width*drawRatio;
    let tr=values['thickRat']||0.02;
    ctx.lineWidth =tr *hi;
    let ox=(width-wi)*0.5;
    let oy=(height-hi)*0.5;

    ctx.moveTo(ctx.lineWidth*0.5+ox, height * 0.6);
    ctx.lineTo(hi * 0.16+ox, height * 0.53);
    ctx.lineTo(hi* 0.3+ox, height -tr*0.5-oy);
    ctx.lineTo(hi* 0.5+ox, hi * tr*0.5+oy);
    ctx.lineTo(width -ctx.lineWidth*0.5-ox, hi*tr*0.5+oy);
    ctx.strokeStyle = values.color||'#ffffff';
    ctx.stroke();

    return RETURN_VALUE(canvas,values);
};

/**
 * 文字
 * @param text 内容
 * @param _sizeX 宽
 * @param _sizeY 高
 * @param values 参数对象:
 * {
 *   shadow {string} color string,
 *   shadowOffsetX {number} pixel value,
 *   shadowOffsetY {number} pixel value,
 *   shadowBlur {number} pixel value,
 *   background {string} color string,
 *   border {string} color string,
 *   borderWidth {number} pixel value,
 *   fontWeight {string} style like 'bold','normal'...,
 *   fontStyle {string} style like 'italic','normal'...,
 *   lineRatio {number} line height ratio,
 *   fontSize {number} pixel value,
 *   fontFamily {string} style like 'HeiTi','KaiTi'...,
 *   fillText {string} color string,
 *   strokeText {string} color string,
 *   strokeWidth {number} pixel value,
 *   charRatio {number} single char width ratio,
 *   alignH {string} style as 'left','center','right',
 *   alignV {string} style as 'top','center','bottom',
 *   x {number} line start horizontal position in pixel value,
 *   y {number} line start vertical position in pixel value
 * }
 * @param targetCanvas  绘制到的canvas
 * @returns {RETURN_VALUE.props|*|Texture}
 */
Texture.text=(text='', _sizeX=256,_sizeY=256,values={},targetCanvas=null)=>{

    let  chr = text.split('');
    let temp = '';
    let row = [];
    let sizeX=targetCanvas?targetCanvas.width:_sizeX;
    let sizeY=targetCanvas?targetCanvas.height:_sizeY;
    let canvas=targetCanvas||document.createElement('canvas');
    if(!targetCanvas) {
        canvas.width = sizeX;
        canvas.height = sizeY;
    }
    let context=canvas.getContext('2d');

    if(values.shadow) {
        context.shadowColor = values.shadow;
        context.shadowOffsetX = values.shadowOffsetX||2;
        context.shadowOffsetY = values.shadowOffsetY||2;
        context.shadowBlur = values.shadowBlur||5;
    }
    if (values.background) {
        context.rect(0, 0, sizeX, sizeY);
        context.fillStyle = values.background;
        context.fill();
    }
    if (values.border) {
        let w = sizeY * (values.borderWidth||0.05);
        context.lineWidth = w;
        context.moveTo(w * 0.5, w * 0.5);
        context.lineTo(w * 0.5, sizeY - w * 0.5);
        context.lineTo(sizeX - w * 0.5, sizeY - w * 0.5);
        context.lineTo(sizeX - w * 0.5, w * 0.5);
        context.lineTo(w * 0.5, w * 0.5);
        context.lineTo(w * 0.5, sizeY * 0.5);
        context.strokeStyle = values.border;
        context.stroke();
    }

    let fontWeight=values.fontWeight||'normal';
    let fontStyle=values.fontStyle||'normal';
    let lineRatio=values['lineRatio']||1;
    let fontSize=values.fontSize||20;
    fontSize/=lineRatio;//....................................................20220104
    let fontFamily=values.fontFamily||'Arial';
    context.font = ''+fontWeight+' '+fontStyle+' '+fontSize+'px '+fontFamily+'';
    if(values.fillText){
        context.fillStyle = values.fillText;
    }
    if(values.strokeText) {
        context.strokeStyle = values.strokeText;
        context.lineWidth=values.strokeWidth||10;
    }
    context.textBaseline = 'middle';
    let ws=[0];
    let rw=0;
    for(let a = 0; a < chr.length; a++){
        rw=text.charCodeAt(a)>255?fontSize:fontSize*(values['charRatio']||0.5);
        if(rw+ws[ws.length-1] >sizeX ){
            row.push(temp);
            ws.push(0);
            temp = '';
        }
        temp += chr[a];
        ws[ws.length-1]+=rw;
    }
    row.push(temp);
    ws.push(rw);
    let alignH=values['alignH']||'left';
    let alignV=values['alignV']||'top';
    let x=values.x||0;
    let y=values.y||0;
    for(let b = 0; b < row.length; b++){
        let tw=0;
        switch (alignH) {
            case 'left':
                tw=x;
                break;
            case 'center':
                tw=(sizeX-ws[b])*0.5;
                break;
            case 'right':
                tw=sizeX-ws[b]-x;
                break;
        }
        let th=0;
        switch (alignV) {
            case 'top':
                th=y;
                break;
            case 'center':
                th=(sizeY-row.length*fontSize*lineRatio)*0.5;
                break;
            case 'bottom':
                tw=(sizeY-row.length*fontSize*lineRatio)-y;
                break;
        }
        if(values.strokeText) {
            context.strokeText(row[b], tw, y + (b + 0.5) * fontSize * lineRatio + th);
        }
        if(values.fillText){
            context.fillText(row[b],tw,y+(b+0.5)*fontSize*lineRatio+th);
        }
    }

    return RETURN_VALUE(canvas,values);
};

/**
 * 圆圈加号
 * @param _size 长（正方形）
 * @param drawRatio 缩放
 * @param values 参数对象
 * @param targetCanvas
 * @returns {RETURN_VALUE.props|*|Texture}
 */
Texture.roundAdd=(_size=256,drawRatio=0.8,values={},targetCanvas=null)=>{
    let size=targetCanvas?Math.min(targetCanvas.width,targetCanvas.height):_size;
    let canvas=targetCanvas||document.createElement('canvas');
    let ctx=canvas.getContext('2d');
    if(!targetCanvas) {
        canvas.width = size;
        canvas.height = size;
    }
    let thickRat=values['thickRat']||0.05;
    let drawRange=size*drawRatio;
    ctx.lineWidth = thickRat*drawRange;

    if(values.shadow) {
        ctx.shadowColor = values.shadow;
        ctx.shadowOffsetX = values.shadowOffsetX||2;
        ctx.shadowOffsetY = values.shadowOffsetY||2;
        ctx.shadowBlur = values.shadowBlur||10;
    }

    let color=values.color||'#ffffff';

    let space=drawRange*(values.space||0.1);
    let hs=drawRange*0.5;
    let hw=ctx.lineWidth*0.5;
    let ofs=(size-drawRange)*0.5;
    ctx.arc(hs+ofs,hs+ofs,hs-hw,0,TPI,true);
    ctx.moveTo(hw+space+ofs, hs+ofs);
    ctx.lineTo(size-hw-space-ofs,hs+ofs);
    ctx.moveTo( hs+ofs,hw+space+ofs);
    ctx.lineTo( hs+ofs,size-hw-space-ofs);
    ctx.strokeStyle = color;
    ctx.stroke();

    return RETURN_VALUE(canvas,values);
};

/**
 * 圆圈减号
 * @param _size 长（正方形）
 * @param drawRatio 缩放
 * @param values 参数对象
 * @param targetCanvas
 * @returns {RETURN_VALUE.props|*|Texture}
 */
Texture.roundMinus=(_size=256,drawRatio=0.8,values={},targetCanvas=null)=>{
    let size=targetCanvas?Math.min(targetCanvas.width,targetCanvas.height):_size;
    let canvas=targetCanvas||document.createElement('canvas');
    let ctx=canvas.getContext('2d');
    if(!targetCanvas) {
        canvas.width = size;
        canvas.height = size;
    }
    let thickRat=values['thickRat']||0.05;
    let drawRange=size*drawRatio;
    ctx.lineWidth = thickRat*drawRange;

    if(values.shadow) {
        ctx.shadowColor = values.shadow;
        ctx.shadowOffsetX = values.shadowOffsetX||2;
        ctx.shadowOffsetY = values.shadowOffsetY||2;
        ctx.shadowBlur = values.shadowBlur||10;
    }

    let color=values.color||'#ffffff';

    let space=drawRange*(values.space||0.1);
    let hs=drawRange*0.5;
    let hw=ctx.lineWidth*0.5;
    let ofs=(size-drawRange)*0.5;
    ctx.arc(hs+ofs,hs+ofs,hs-hw,0,TPI,true);
    ctx.moveTo(hw+space+ofs, hs+ofs);
    ctx.lineTo(size-hw-space-ofs,hs+ofs);
    ctx.strokeStyle = color;
    ctx.stroke();

    return RETURN_VALUE(canvas,values);
};

/**
 * 长圆
 * @param _width 宽
 * @param _height 高
 * @param drawRatio 缩放
 * @param values
 * @param targetCanvas
 * @returns {RETURN_VALUE.props|*|Texture}
 */
Texture.longRound=(_width=512,_height=128,drawRatio=0.9,values={},targetCanvas=null)=>{
    let width=targetCanvas?targetCanvas.width:_width;
    let height=targetCanvas?targetCanvas.height:_height;
    let canvas=targetCanvas||document.createElement('canvas');
    let ctx=canvas.getContext('2d');
    if(!targetCanvas) {
        canvas.width = width;
        canvas.height = height;
    }
    let thickRat=values['thickRat']||0.05;
    let dW=width*drawRatio;
    let dH=height*drawRatio;
    let lw=dH*thickRat;

    let ofx=(width-dW)*0.5;
    let ofy=(height-dH)*0.5;
    let oft=lw*0.5;
    let px=oft+ofx+dH*0.5;
    let py=height*0.5;
    let r=dH*0.5-oft;
    ctx.arc(px,py,r,-HPI,HPI,true);
    ctx.arc(width-px,py,r,HPI,TPI-HPI,true);
    ctx.lineTo(px,oft+ofy);

    if(values.fill){
        ctx.fillStyle=values.fill;
        ctx.fill();
    }
    if(values.stroke){
        ctx.strokeStyle = values.stroke;
        ctx.lineWidth = lw;
        ctx.stroke();
    }

    return RETURN_VALUE(canvas,values);
};

/**
 * 圆角矩形
 * @param _width
 * @param _height
 * @param drawRatio
 * @param values
 * @param targetCanvas
 * @returns {RETURN_VALUE.props|*|Texture}
 */
Texture.roundCorner=(_width=256,_height=128,drawRatio=0.9,values={},targetCanvas=null)=>{
    let width=targetCanvas?targetCanvas.width:_width;
    let height=targetCanvas?targetCanvas.height:_height;
    let fw=width*drawRatio;
    let fh=height*drawRatio;
    let ow=(width-fw)*0.5;
    let oh=(height-fh)*0.5;
    let canvas=targetCanvas||document.createElement('canvas');
    if(!targetCanvas){
        canvas.width=width;
        canvas.height=height;
    }
    let ctx=canvas.getContext('2d');

    let r0=values['radiusLeftBottom']||(values['radius']||0);
    let r1=values['radiusLeftTop']||(values['radius']||0);
    let r2=values['radiusRightTop']||(values['radius']||0);
    let r3=values['radiusRightBottom']||(values['radius']||0);

    ctx.beginPath();
    ctx.arc(ow+r0,height-oh-r0,r0,HPI,PI,false);
    ctx.arc(ow+r1,oh+r1,r1,PI,-HPI,false);
    ctx.arc(width-ow-r2,oh+r2,r2,-HPI,0,false);
    ctx.arc(width-ow-r3,height-oh-r3,r3,0,HPI,false);
    ctx.lineTo(ow+r0,height-oh);
    ctx.closePath();

    if(values.shadow) {
        ctx.shadowColor = values.shadow;
        ctx.shadowOffsetX = values.shadowOffsetX||2;
        ctx.shadowOffsetY = values.shadowOffsetY||2;
        ctx.shadowBlur = values.shadowBlur||5;
    }

    if(values.fill){
        ctx.fillStyle=values.fill;
        ctx.fill();
    }
    if(values.stroke){
        if(values.lineDash)ctx.setLineDash(values.lineDash);
        ctx.strokeStyle = values.stroke;
        ctx.lineWidth = values.lineWidth||1;
        ctx.stroke();
    }

    return RETURN_VALUE(canvas,values);
};

/**
 * 位置标记
 * @param _size 宽（高自动计算）
 * @param halfAngle 箭头半角
 * @param drawRatio 缩放
 * @param values
 * @param targetCanvas
 * @returns {RETURN_VALUE.props|*|Texture}
 */
Texture.locationMark=(_size=200,halfAngle=30,drawRatio=0.9,values={},targetCanvas=null)=>{
    let ha=halfAngle*D2R;
    let sha=1/Math.sin(ha);
    let width=targetCanvas?targetCanvas.width:_size;
    let height=targetCanvas?targetCanvas.height:_size*0.5+_size*0.5*sha;
    let canvas=targetCanvas||document.createElement('canvas');
    let ctx=canvas.getContext('2d');
    if(!targetCanvas) {
        canvas.width = width;
        canvas.height = height;
    }
    let thickRat=values['thickRat']||0.05;
    let dW=width*drawRatio;
    let dH=height*drawRatio;
    let lw=dH*thickRat;

    let ofx=(width-dW)*0.5;
    let ofy=(height-dH)*0.5;
    let oft=lw*0.5;
    let px=width*0.5;
    let r=dW*0.5-ofx-oft;
    ctx.moveTo(px,ofy+oft+r+r*sha);
    ctx.lineTo(px+r*Math.cos(ha),ofy+oft+r+r*Math.sin(ha));
    ctx.arc(px,ofy+oft+r,r,ha,PI-ha,true);
    ctx.lineTo(px,ofy+oft+r+r*sha);

    if(values.fill){
        ctx.fillStyle=values.fill;
        ctx.fill();
    }
    if(values.stroke){
        ctx.lineCap=values.lineCap||'round';
        ctx.strokeStyle = values.stroke;
        ctx.lineWidth = lw;
        ctx.stroke();
    }

    return RETURN_VALUE(canvas,values);
};

/**
 * 渐变
 * @param _width 宽
 * @param _height 高
 * @param drawRatio 绘制比例
 * @param values
 * @param targetCanvas
 * @returns {RETURN_VALUE.props|*|Texture}
 */
Texture.gradient=(_width,_height,drawRatio=0.9,values={},targetCanvas=null)=>{
    let width=targetCanvas?targetCanvas.width:_width;
    let height=targetCanvas?targetCanvas.height:_height;
    let canvas=targetCanvas||document.createElement('canvas');
    let ctx=canvas.getContext('2d');
    if(!targetCanvas) {
        canvas.width = width;
        canvas.height = height;
    }
    let dW=width*drawRatio;
    let dH=height*drawRatio;

    let grad=null;
    let x0=values['x0']||0;
    let y0=values['y0']||0;
    let x1=values['x1']||dW;
    let y1=values['y1']||0;
    let r0=values['r0']||dW*0.3;
    let r1=values['r1']||dH*0.3;
    if(values['radiant']){
        grad=ctx.createRadialGradient(x0,y0,r0,x1,y1,r1);
    }else{
        grad=ctx.createLinearGradient(x0,y0,x1,y1);
    }
    grad.addColorStop(values['offsetStart']||0,values['colorStart']||'#808080');
    grad.addColorStop(values['offsetEnd']||1,values['colorEnd']||'#222222');
    ctx.fillStyle=grad;
    ctx.fillRect((width-dW)*0.5,(height-dH)*0.5,dW,dH);

    return RETURN_VALUE(canvas,values);
};

export default Texture;